﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using UnityEngine;

public static class StringTools
{
    static System.Object strBuilderLock = new System.Object();
    static StringBuilder strBuilder = new StringBuilder();
    static string[] buffer1 = new string[1];
    static string[] buffer2 = new string[2];
    static string[] buffer3 = new string[3];
    static string[] buffer4 = new string[4];
    static string[] buffer5 = new string[5];
    static string[] buffer6 = new string[6];
    
    public static string Format(string msg,string moduleName)
    {
        try
        {
            lock (strBuilder)
            {
                strBuilder.Clear();
                strBuilder.Capacity = msg.Length;
                TryAppendFrameCount();
                AppendModuleName(moduleName);
                strBuilder.Append(msg);
                return strBuilder.ToString();
            }
        }
        catch (Exception e)
        {
            return "StringTools.Formate Exception, msg:" +msg+" ,moduleName:"+moduleName+" ,ExceptionMessage:"+ e.Message;
        }
    }
    
    public static string Format(string format,string moduleName, string args0)
    {
        buffer1[0] = args0;
        return Format(format,moduleName, buffer1);
    }
    public static string Format(string format,string moduleName,string args0, string args1)
    {
        buffer2[0] = args0;
        buffer2[1] = args1;
        return Format(format,moduleName, buffer2);
    }
    public static string Format(string format,string moduleName, string args0, string args1, string args2)
    {
        buffer3[0] = args0;
        buffer3[1] = args1;
        buffer3[2] = args2;
        return Format(format,moduleName, buffer3);
    }
    public static string Format(string format,string moduleName, string args0, string args1, string args2, string args3)
    {
        buffer4[0] = args0;
        buffer4[1] = args1;
        buffer4[2] = args2;
        buffer4[3] = args3;
        return Format(format,moduleName, buffer4);
    }
    public static string Format(string format,string moduleName, string args0, string args1, string args2, string args3, string args4)
    {
        buffer5[0] = args0;
        buffer5[1] = args1;
        buffer5[2] = args2;
        buffer5[3] = args3;
        buffer5[4] = args4;
        return Format(format,moduleName, buffer5);
    }
    public static string Format(string format,string moduleName, string args0, string args1, string args2, string args3, string args4, string args5)
    {
        buffer6[0] = args0;
        buffer6[1] = args1;
        buffer6[2] = args2;
        buffer6[3] = args3;
        buffer6[4] = args4;
        buffer6[5] = args5;
        return Format(format,moduleName, buffer6);
    }

    public static string Format(string format,string moduleName, params object[] args)
    {
        try
        {
            lock (strBuilder)
            {
                strBuilder.Clear();
                strBuilder.Capacity = format.Length + (args.Length * 8);
                TryAppendFrameCount();
                AppendModuleName(moduleName);
                strBuilder.AppendFormat(null, format, args);
                return strBuilder.ToString();
            }
        }
        catch (Exception e)
        {
            return "StringTools.Formate Exception, formate:" +format+" ,args:"+string.Join(";", args)+" ,moduleName:"+moduleName+" ,ExceptionMessage:"+ e.Message;
        }
    }
    
    private static string Format(string format,string moduleName, string[] args)
    {
        try
        {
            lock (strBuilder)
            {
                strBuilder.Clear();
                strBuilder.Capacity = format.Length + (args.Length * 8);
                TryAppendFrameCount();
                AppendModuleName(moduleName);
                strBuilder.AppendFormat(null, format, args);
                return strBuilder.ToString();
            }
        }
        catch (Exception e)
        {
            return "StringTools.Formate Exception, formate:" +format+" ,args:"+string.Join(";", args)+" ,moduleName:"+moduleName+" ,ExceptionMessage:"+ e.Message;
        }
    }

    /// <summary>
    /// 尝试获取并追加帧号信息，在一些特殊情况，序列化/非主线程/构造函数等处Unity不支持获取帧号,这种情况不追加
    /// </summary>
    /// <returns></returns>
    private static bool TryAppendFrameCount()
    {
        try
        {
            if (LogAgent.IsMainThread()) //UnityEngine.Time.frameCount只能在主线程中执行，日志接口可以在任何线程中调用
            {   
                strBuilder.AppendFormat("[{0}]", UnityEngine.Time.frameCount);
                return true;
            }
        }
        catch (Exception ex)
        {
            Debug.LogException(ex);
        }
        return false;
    }
    
    private static void AppendModuleName(string moduleName)
    {
        if (!string.IsNullOrEmpty(moduleName))
        {
            strBuilder.AppendFormat("[{0}]", moduleName);
        }
    }
}
